﻿using System.Windows;
using System;

namespace ZOIL.Framework.Presentation
{
	/// <summary>
	/// Zoom Modifiers affect certain attributes in relation to the current
	/// zoom level. They always link to a dependency property.
	/// 
	/// Note that the dependency property's value is stored during the first
	/// modifier update. Subsequent changes to the property value will
	/// therefore be ignored by later updates and have to be done using the
	/// method provided by the modifier. A better solution would be to
	/// automatically update the original value each time the property's
	/// value changes.
	/// </summary>
    public abstract class ZoomModifier : DependencyObject
    {
        #region protected properties

        #region OriginalValue

        private object _originalValue = null;

        /// <summary>
        /// 
        /// </summary>
        protected object OriginalValue
        {
            get
            {
                return _originalValue;
            }
            set
            {
                _originalValue = value;
            }
        }

        #endregion

        #endregion

        #region dp

        /// <summary>
        /// 
        /// </summary>
        public static readonly DependencyProperty PropertyProperty = DependencyProperty.Register("Property", typeof(DependencyProperty), typeof(ZoomModifier));

        /// <summary>
        /// 
        /// </summary>
        public DependencyProperty Property
        {
            get { return (DependencyProperty)this.GetValue(PropertyProperty); }
            set { this.SetValue(PropertyProperty, value); }
        }

        #endregion

        #region public methods

        /// <summary>
        /// Updates the linked property's value to react to changes in the
        /// landscape's zoom level.
        /// </summary>
        /// <param name="source">The control whose property is to be updated.</param>
        /// <param name="zoom">The landscape's zoom level.</param>
        public virtual void Update(DependencyObject source, double zoom)
        {
            if (source == null)
            {
                throw new ArgumentNullException("source");
            }

            if (OriginalValue == null)
            {
                OriginalValue = source.GetValue(this.Property);

                // TODO: ideally, we should look for changes to the property
                //this.Property.OverrideMetadata(typeof(ZoomModifier), new PropertyMetadata(
                //	new PropertyChangedCallback(OnValueChanged)));
            }
        }

        /// <summary>
        /// Forces the linked property to be updated.
        /// Update() should be called immediately afterwards.
        /// </summary>
        /// <param name="source"></param>
        /// <param name="value"></param>
        public void ChangePropertyValue(DependencyObject source, object value)
        {
            if (source == null)
                throw new ArgumentNullException("source");

            source.SetValue(this.Property, value);
            OriginalValue = value;
        }

        #endregion

        #region protected methods

        /// <summary>
        /// Calculates the correct zoom percentage that is to be used for
        /// modifier transformations.
        /// </summary>
        /// <param name="zoom">The landscape's zoom value.</param>
        /// <param name="modifier">
        /// Modifier value; 1.0 for normal zooming, 0.0 for fixed-size zooming,
        /// negative values for anti-zoom.
        /// </param>
        /// <returns>Modifier transformation value.</returns>
        protected static double Interpolate(double zoom, double modifier)
        {
            double inverse = (1.0 / zoom);
            return (inverse + modifier * (1.0 - inverse));
        }

        #endregion
    }

	

	

	
}
